/*
 * Copyright 2012 Evgeny Shishkin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.devspark.appmsg;

import org.amphiprion.montrictracv4.R;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import android.widget.TextView;

/**
 * In-layout notifications. Based on {@link android.widget.Toast} notifications and article by Cyril Mottier (http://android.cyrilmottier.com/?p=773).
 * 
 * @author e.shishkin
 * 
 */
public class AppMsg {

	/**
	 * Show the view or text notification for a short period of time. This time could be user-definable. This is the default.
	 * 
	 * @see #setDuration
	 */
	public static final int LENGTH_SHORT = 3000;

	/**
	 * Show the view or text notification for a long period of time. This time could be user-definable.
	 * 
	 * @see #setDuration
	 */
	public static final int LENGTH_LONG = 5000;

	/**
	 * Show the text notification for a long period of time with a negative style.
	 */
	public static final Style STYLE_ALERT = new Style(LENGTH_LONG, R.color.alert);

	/**
	 * Show the text notification for a short period of time with a positive style.
	 */
	public static final Style STYLE_CONFIRM = new Style(LENGTH_SHORT, R.color.confirm);

	/**
	 * Show the text notification for a short period of time with a neutral style.
	 */
	public static final Style STYLE_INFO = new Style(LENGTH_SHORT, R.color.info);

	private final Activity mContext;
	private int mDuration = LENGTH_SHORT;
	private View mView;
	private LayoutParams mLayoutParams;
	private Fragment fragment;

	/**
	 * Construct an empty AppMsg object. You must call {@link #setView} before you can call {@link #show}.
	 * 
	 * @param context
	 *            The context to use. Usually your {@link android.app.Activity} object.
	 */
	public AppMsg(Activity context) {
		mContext = context;
	}

	/**
	 * Make a {@link AppMsg} that just contains a text view.
	 * 
	 * @param context
	 *            The context to use. Usually your {@link android.app.Activity} object.
	 * @param text
	 *            The text to show. Can be formatted text.
	 * @param duration
	 *            How long to display the message. Either {@link #LENGTH_SHORT} or {@link #LENGTH_LONG}
	 * 
	 */
	public static AppMsg makeText(Activity context, CharSequence text, Style style) {
		AppMsg result = new AppMsg(context);

		LayoutInflater inflate = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View v = inflate.inflate(R.layout.app_msg, null);
		// v.setBackgroundResource(style.background);

		TextView tv = (TextView) v.findViewById(android.R.id.message);
		tv.setText(text);

		result.mView = v;
		result.mDuration = style.duration;

		return result;
	}

	public Fragment getFragment() {
		return fragment;
	}

	public AppMsg setFragment(Fragment fragment) {
		this.fragment = fragment;
		return this;
	}

	/**
	 * Make a {@link AppMsg} that just contains a text view with the text from a resource.
	 * 
	 * @param context
	 *            The context to use. Usually your {@link android.app.Activity} object.
	 * @param resId
	 *            The resource id of the string resource to use. Can be formatted text.
	 * @param duration
	 *            How long to display the message. Either {@link #LENGTH_SHORT} or {@link #LENGTH_LONG}
	 * 
	 * @throws Resources.NotFoundException
	 *             if the resource can't be found.
	 */
	public static AppMsg makeText(Activity context, int resId, Style style) throws Resources.NotFoundException {
		return makeText(context, context.getResources().getText(resId), style);
	}

	/**
	 * Show the view for the specified duration.
	 */
	public void show() {
		MsgManager manager = MsgManager.getInstance();
		manager.add(this);
	}

	/**
	 * @return <code>true</code> if the {@link AppMsg} is being displayed, else <code>false</code>.
	 */
	boolean isShowing() {
		return mView != null && mView.getParent() != null;
	}

	/**
	 * Close the view if it's showing, or don't show it if it isn't showing yet. You do not normally have to call this. Normally view will disappear on its own after the appropriate duration.
	 */
	public void cancel() {
		MsgManager.getInstance().clearMsg(this);
	}

	/**
	 * Cancels all queued {@link AppMsg}s. If there is a {@link AppMsg} displayed currently, it will be the last one displayed.
	 */
	public static void cancelAll() {
		MsgManager.getInstance().clearAllMsg();
	}

	/**
	 * Return the activity.
	 */
	public Activity getActivity() {
		return mContext;
	}

	/**
	 * Set the view to show.
	 * 
	 * @see #getView
	 */
	public void setView(View view) {
		mView = view;
	}

	/**
	 * Return the view.
	 * 
	 * @see #setView
	 */
	public View getView() {
		return mView;
	}

	/**
	 * Set how long to show the view for.
	 * 
	 * @see #LENGTH_SHORT
	 * @see #LENGTH_LONG
	 */
	public void setDuration(int duration) {
		mDuration = duration;
	}

	/**
	 * Return the duration.
	 * 
	 * @see #setDuration
	 */
	public int getDuration() {
		return mDuration;
	}

	/**
	 * Update the text in a AppMsg that was previously created using one of the makeText() methods.
	 * 
	 * @param resId
	 *            The new text for the AppMsg.
	 */
	public void setText(int resId) {
		setText(mContext.getText(resId));
	}

	/**
	 * Update the text in a AppMsg that was previously created using one of the makeText() methods.
	 * 
	 * @param s
	 *            The new text for the AppMsg.
	 */
	public void setText(CharSequence s) {
		if (mView == null) {
			throw new RuntimeException("This AppMsg was not created with AppMsg.makeText()");
		}
		TextView tv = (TextView) mView.findViewById(android.R.id.message);
		if (tv == null) {
			throw new RuntimeException("This AppMsg was not created with AppMsg.makeText()");
		}
		tv.setText(s);
	}

	/**
	 * Gets the crouton's layout parameters, constructing a default if necessary.
	 * 
	 * @return the layout parameters
	 */
	public LayoutParams getLayoutParams() {
		if (mLayoutParams == null) {
			mLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		}
		return mLayoutParams;
	}

	/**
	 * Sets the layout parameters which will be used to display the crouton.
	 * 
	 * @param layoutParams
	 *            The layout parameters to use.
	 * @return <code>this</code>, for chaining.
	 */
	public AppMsg setLayoutParams(LayoutParams layoutParams) {
		mLayoutParams = layoutParams;
		return this;
	}

	/**
	 * Constructs and sets the layout parameters to have some gravity.
	 * 
	 * @param gravity
	 *            the gravity of the Crouton
	 * @return <code>this</code>, for chaining.
	 * @see android.view.Gravity
	 */
	public AppMsg setLayoutGravity(int gravity) {
		mLayoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, gravity);
		return this;
	}

	/**
	 * The style for a {@link AppMsg}.
	 * 
	 * @author e.shishkin
	 */
	public static class Style {

		private final int duration;
		private final int background;

		/**
		 * Construct an {@link AppMsg.Style} object.
		 * 
		 * @param duration
		 *            How long to display the message. Either {@link #LENGTH_SHORT} or {@link #LENGTH_LONG}
		 * @param resId
		 *            resource for AppMsg background
		 */
		public Style(int duration, int resId) {
			this.duration = duration;
			this.background = resId;
		}

		/**
		 * Return the duration in milliseconds.
		 */
		public int getDuration() {
			return duration;
		}

		/**
		 * Return the resource id of background.
		 */
		public int getBackground() {
			return background;
		}

		@Override
		public boolean equals(Object o) {
			if (!(o instanceof AppMsg.Style)) {
				return false;
			}
			Style style = (Style) o;
			return style.duration == duration && style.background == background;
		}

	}

}